package com.nuc.bigdata.aspect;

import com.nuc.bigdata.annotation.Permission;
import com.nuc.bigdata.domain.entity.User;
import com.nuc.bigdata.enums.UserRoleEnum;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpSession;
import java.lang.reflect.Method;

/**
 * @author JackLuo
 * @date 2019/10/23
 */
@Aspect
@Component
public class PermissionAdvice {

    /**
     * 定义切点为Permission注解
     */
    @Pointcut("@annotation(com.nuc.bigdata.annotation.Permission)")
    public void annotationPointcut() {
    }


    @Around("annotationPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) {
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpSession session = requestAttributes.getRequest().getSession();

        Method annotationMethod = getAnnotationMethod(joinPoint);
        assert annotationMethod != null;
        Permission permission = annotationMethod.getAnnotation(Permission.class);
        if (permission.value()) {
            User user = (User) session.getAttribute(UserRoleEnum.USER.getRoleMsg());
            if (StringUtils.isEmpty(user)) {
                return "forward:403";
            } else {
                if (doAuthority(user)) {
                    try {
                        return joinPoint.proceed();
                    } catch (Throwable throwable) {
                        throwable.printStackTrace();
                    }
                }
            }
        }
        return "forward:403";

    }


    @After("annotationPointcut()")
    public void after() {

    }

    @AfterReturning(pointcut = "annotationPointcut()", returning = "result")
    public void afterReturning(Object result) {

    }

    /**
     * 获取当前注解的方法
     * @param joinPoint
     * @return 注解方法
     */
    private Method getAnnotationMethod(ProceedingJoinPoint joinPoint) {
        MethodSignature msig = (MethodSignature) joinPoint.getSignature();
        Object target = joinPoint.getTarget();
        try {
            return target.getClass().getMethod(msig.getName(), msig.getParameterTypes());
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对session中的user进行角色校验
     * @param user
     * @return user的role为管理员就是true
     */
    private boolean doAuthority(User user) {
        return user.getRole().equals(UserRoleEnum.ADMIN.getRoleNumber());
    }
}
